package com.yupi.yuojcodesandbox.utils;

import cn.hutool.core.util.StrUtil;
import com.yupi.yuojcodesandbox.model.ExcuteMessage;
import io.netty.util.internal.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.StopWatch;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class ProcessUtils {

    //因为返回值有正常输出和错误输出 不是一个字符串所以需要定义一个对象去返回
    public static ExcuteMessage runProcessAndGetMessage(Process runProcess ,String opName) {
        ExcuteMessage excuteMessage = new ExcuteMessage();
        try {
            //在代码程序执行的内部执行时间的计算会更加准确
            StopWatch stopWatch = new StopWatch();
            stopWatch.start();
            // 等待程序执行，获取错误码 也会是等待compileProcess程序编译的完成拿到一个错误码 就可以从错误码中判断程序是正常退出还是异常退出
            int exitValue = runProcess.waitFor();
            excuteMessage.setExitValue(exitValue);
            // 正常退出
            if (exitValue == 0) {
                System.out.println(opName + "成功");
                // 分批获取进程的正常输出 因为错误码的信息是写在了输入流里面 所以需要从输入流里面读取进程的信息
                //BufferedReader表示以长串，分批的方式去读取  InputStreamReader这个是读取输入流的读取器
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(runProcess.getInputStream()));
                //字符串构造器把读取出来的多行信息构成一行字符串便于展示
//                StringBuilder compileOutputStringBuilder = new StringBuilder();
                List<String> outputStrList = new ArrayList<>();
                // 逐行读取 因为BufferedReader可能会多次的去读取信息 因为是一个缓冲区不一定只有一行信息 所以可能会读取多行信息需要while循环一下
                String compileOutputLine;
                //从bufferedReader对象中读取一行文本，并将其赋值给compileOutputLine变量。
                //检查compileOutputLine是否为null，如果不为null，则继续循环执行循环体；如果为null，则结束循环
                while ((compileOutputLine = bufferedReader.readLine()) != null) {
//                    compileOutputStringBuilder.append(compileOutputLine).append("\n");
                    outputStrList.add(compileOutputLine);
                }
                excuteMessage.setMessage(StringUtils.join(outputStrList,"\n"));
                System.out.println(StringUtils.join(outputStrList,"\n"));
            } else {
                // 异常退出
                System.out.println(opName + "失败，错误码： " + exitValue);
                // 分批获取进程的正常输出
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(runProcess.getInputStream()));
//                //字符串构造器把读取出来的多行信息构成一行字符串便于展示
//                StringBuilder compileOutputStringBuilder = new StringBuilder();
//                // 逐行读取
//                String compileOutputLine;
//                while ((compileOutputLine = bufferedReader.readLine()) != null) {
//                    compileOutputStringBuilder.append(compileOutputLine).append("\n");
//                }
//                excuteMessage.setMessage(compileOutputStringBuilder.toString());


                List<String> outputStrList = new ArrayList<>();
                // 逐行读取 因为BufferedReader可能会多次的去读取信息 因为是一个缓冲区不一定只有一行信息 所以可能会读取多行信息需要while循环一下
                String compileOutputLine;
                //从bufferedReader对象中读取一行文本，并将其赋值给compileOutputLine变量。
                //检查compileOutputLine是否为null，如果不为null，则继续循环执行循环体；如果为null，则结束循环
                while ((compileOutputLine = bufferedReader.readLine()) != null) {
//                    compileOutputStringBuilder.append(compileOutputLine).append("\n");
                    outputStrList.add(compileOutputLine);
                }
                excuteMessage.setMessage(StringUtils.join(outputStrList,"\n"));
                System.out.println(StringUtils.join(outputStrList,"\n"));


                // getErrorStream 程序异常退出后分批获取进程的错误输出信息
                BufferedReader errorBufferedReader = new BufferedReader(new InputStreamReader(runProcess.getErrorStream()));
                //字符串构造器把读取出来的多行信息构成一行字符串便于展示
//                StringBuilder errorCompileOutputStringBuilder = new StringBuilder();
//                // 逐行读取
//                String errorCompileOutputLine;
//                while ((errorCompileOutputLine = errorBufferedReader.readLine()) != null) {
//                    errorCompileOutputStringBuilder.append(errorCompileOutputLine).append("\n");
//                }
//                excuteMessage.setErrorMessage(errorCompileOutputStringBuilder.toString());
//                System.out.println(compileOutputStringBuilder);
//                System.out.println(errorCompileOutputStringBuilder);
                List<String> errorOutputStrList = new ArrayList<>();
                // 逐行读取 因为BufferedReader可能会多次的去读取信息 因为是一个缓冲区不一定只有一行信息 所以可能会读取多行信息需要while循环一下
                String errorCompileOutputLine;
                //从bufferedReader对象中读取一行文本，并将其赋值给compileOutputLine变量。
                //检查compileOutputLine是否为null，如果不为null，则继续循环执行循环体；如果为null，则结束循环
                while ((errorCompileOutputLine = bufferedReader.readLine()) != null) {
//                    compileOutputStringBuilder.append(compileOutputLine).append("\n");
                    errorOutputStrList.add(errorCompileOutputLine);
                }
                excuteMessage.setMessage(StringUtils.join(errorOutputStrList,"\n"));
                System.out.println(StringUtils.join(errorOutputStrList,"\n"));
            }
                stopWatch.stop();
            excuteMessage.setTime(stopWatch.getLastTaskTimeMillis());
            }catch(Exception e){
                e.printStackTrace();
            }
            return excuteMessage;
        }


    public static ExcuteMessage runInteractProcessAndGetMessage(Process runProcess ,String opName, String args) {
        ExcuteMessage executeMessage = new ExcuteMessage();
        try {
            //  创建一个输出流 把参数输入进去 就是模仿用户在控制台输入参数 然后向控制台输入程序
            OutputStream outputStream = runProcess.getOutputStream();
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
            String[] s = args.split(" ");
            String join = StrUtil.join("\n", s) + "\n";
            outputStreamWriter.write(join);
            // 相当于按了回车，执行输入的发送
            outputStreamWriter.flush();

            // 分批获取进程的正常输出
            InputStream inputStream = runProcess.getInputStream();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            StringBuilder compileOutputStringBuilder = new StringBuilder();
            // 逐行读取
            String compileOutputLine;
            while ((compileOutputLine = bufferedReader.readLine()) != null) {
                compileOutputStringBuilder.append(compileOutputLine);
            }
            executeMessage.setMessage(compileOutputStringBuilder.toString());
            // 记得资源的释放，否则会卡死
            outputStreamWriter.close();
            outputStream.close();
            inputStream.close();
            runProcess.destroy();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return executeMessage;
    }
    }
